namespace SCIENEW.Tech {
    /// <summary>
    /// 科技树，采用邻接表数据结构
    /// </summary>
    public class TechTree {
        Dictionary<string, TechNode> m_nodes = new();

        public Dictionary<string, TechNode> TechNodes => m_nodes;

        /// <summary>
        /// 获得一个科技树节点
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public TechNode GetOrCreateNode(string name) {
            if (!m_nodes.TryGetValue(name, out var node)) {
                node = new TechNode(name);
                m_nodes[name] = node;
            }
            return node;
        }

        /// <summary>
        /// 添加科技树节点依赖关系
        /// </summary>
        /// <param name="techName"></param>
        /// <param name="dependencyName"></param>
        public void AddDependency(string techName, string dependencyName) {
            var techNode = GetOrCreateNode(techName);
            var dependencyNode = GetOrCreateNode(dependencyName);
            techNode.AddDependency(dependencyNode);
        }

        /// <summary>
        /// 添加科技树节点的多个依赖关系
        /// </summary>
        /// <param name="techName">科技名称</param>
        /// <param name="dependenciesNames">多个依赖的科技名称</param>
        public void AddDependency(string techName, IEnumerable<string> dependenciesNames) {
            var techNode = GetOrCreateNode(techName);
            foreach (var dependencyName in dependenciesNames) {
                var dependencyNode = GetOrCreateNode(dependencyName);
                techNode.AddDependency(dependencyNode);
            }
        }

        /// <summary>
        /// 获得科技树节点
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public TechNode GetNode(string name) {
            m_nodes.TryGetValue(name, out var node);
            return node;
        }

        /// <summary>
        /// 依据阶段获取节点
        /// </summary>
        /// <param name="stage"></param>
        /// <returns></returns>
        public TechNode[] GetNodeByStage(int stage) => m_nodes.Values.Where(x => x.Stage == stage).ToArray();

        /// <summary>
        /// 获取所有解锁了的节点
        /// </summary>
        /// <returns></returns>
        public TechNode[] GetUnlockedNodes() => m_nodes.Values.Where(x => !x.IsLocked).ToArray();

        /// <summary>
        /// 解锁节点
        /// </summary>
        /// <param name="name"></param>
        /// <returns>是否重复解锁</returns>
        public bool UnlockNode(string name, out TechNode unlockedNode) {
            unlockedNode = null;
            foreach (var node in m_nodes) {
                if (node.Key == name) {
                    bool isRepeatOperate = !node.Value.IsLocked;
                    node.Value.IsLocked = false;
                    unlockedNode = node.Value;
                    return isRepeatOperate;
                }
            }
            return false;
        }

        /// <summary>
        /// 依据图标方块ID解锁节点
        /// </summary>
        /// <param name="iconBlock"></param>
        /// <returns>是否重复解锁</returns>
        public bool UnlockNode(int iconBlock, out TechNode unlockedNode) {
            unlockedNode = null;
            foreach (var node in m_nodes) {
                if (node.Value.IconBlock == iconBlock) {
                    bool isRepeatOperate = !node.Value.IsLocked;
                    node.Value.IsLocked = false;
                    unlockedNode = node.Value;
                    return isRepeatOperate;
                }
            }
            return false;
        }

        /// <summary>
        /// 几所一大批节点
        /// </summary>
        /// <param name="nodes"></param>
        public void UnlockNodes(IEnumerable<string> nodes) {
            foreach (var node in nodes) {
                UnlockNode(node, out _);
            }
        }

        /// <summary>
        /// 锁定所有节点
        /// </summary>
        public void LockAllNodes() {
            foreach (var node in m_nodes) {
                node.Value.IsLocked = true;
            }
        }
    }
}